iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 16
0
自我挑戰組

WordPress 客製化從 0 開始系列 第 16

Day 16 用 WordPress 為網站增加動畫效果:GSAP

  • 分享至 

  • xImage
  •  

大家好,我是 Eric。

昨天介紹了在 WordPress 中加入 Animation on Scroll 的效果,並說明如何用 wp_enqueueu_scripts 在自己的 WordPress 網站中引入 JavaScript 函式庫。今天,我們要再來介紹另一款與動畫有關的函式庫:GSAP。

為什麼要使用 GSAP?

相較於昨天介紹的 AOS,是根據瀏覽器的捲動事件觸發動畫事件。GSAP 使用了「時間軸」的概念。對於繪製動畫,或是有剪輯影片經驗的人來說,時間軸有助於掌握動畫節奏。

除了時間軸以外,GSAP 也同時可以透過附加的外掛,來選擇特殊的 DOM 元素,例如虛擬元素。

引用 GSAP

和昨天一樣,我們先透過 wp_enqueue_scripts 的方式引用 GSAP。

function eric_enqueue_gsap(){
    wp_enqueue_script( 'gsap', 'https://cdnjs.cloudflare.com/ajax/libs/gsap/3.5.1/gsap.min.js' );
    wp_enqueue_script( 'gsap-set', '儲存路徑/gsap-set.js' );
    /** 這個檔案主要是用來存放接下來提到的時間軸 */
}
add_action( 'wp_enqueue_scripts', 'eric_enqueue_gsap' );

GSAP 基本操作

GSAP 的基本語法如下:

var tl = new TimelineMax(); // 建立一條新的時間軸
tl.to( '選擇器', {duration: 秒數, 樣式屬性: 屬性值})
  .to( '選擇器', 動畫持續秒數, {樣式屬性: 屬性值, 樣式屬性 2: 屬性值 2})
  .to( '選擇器', 動畫持續秒數, {樣式屬性: 屬性值, 樣式屬性 2: 屬性值 2}, "時間延遲";
/* 2020/10/08 更新
 * 從 GSAP 3.0 開始,官方建議改用 var tl = gsap.timeline(); 的方式建立時間軸,
 * 並表示從 GSAP 4 以後,將會廢除 TimelineMax() 的方法。
 */

這邊簡單介紹一下上面語法中可以使用的屬性值:

名稱 | 說明
-------+-------
選擇器 | CSS 選擇器,無法選擇虛擬元素。
duration | 必須是數字秒數。
樣式屬性 | CSS 樣式,如果遇到像是 background-color 這種有 - 符號的屬性,則要用 backgroundColor 這種方式來表示。
時間延遲 | 預設是 0,代表前一個動畫結束後,立刻接續下一個動畫。如果是 "-=1",則是在前一動畫結束前 1 秒鐘,接續下一個動畫。
repeat | 重複次數,如果填 1,則代表除了原本第一次外,會「再」重複 1 次。

透過這個函式庫,我們可以先做出下列的動畫:

<style>
#animation1 {
  opacity: 0;
}
</style>
<div id="animation1">
  <p id="obj1">這是第一段</p>
</div>
<script>
var tl1 = new TimelineMax(); //建立一條新的時間軸
tl1.to("#animation1", {duration: 0.5,opacity:1,repeat:10}); 
//讓 #animation1 從原本不透明度 0,在 0.5 秒內變成 1,額外重複 10 次
</script>

透過 new TimelineMax();,我們可以建立不只一條時間軸。

<div id="animation1">
  <p id="obj1">這是第一段</p>
</div>

<div id="animation2">
  <p id="obj2">這是第二段</p>
</div>
<script>
var tl1 = new TimelineMax();
tl1.to("#animation1", {duration: 0.5,opacity:1,repeat:10});

var tl2 = new TimelineMax();
tl2.to("#animation1", 5, {
  color: "#ff02a8"
}, "-=1")
  .to("#animation2", 1, {
  color: "blue"
})
  .to("#animation2", 1, {
  backgroundColor: "#aaaa00",
  padding: "10px"
})
  .to("#obj2", 0.5, {
  backgroundColor: "#fff",
  width: "30%"
}, "-=1");
</script>

我們在第二條時間軸製作了比較多的設定,但是基本上我們還是能將兩條時間軸合併起來。除非我們要分別控制:

<button id="trigger-animation1">動畫 1 暫停</button>
<button id="trigger-animation2">動畫 2 暫停</button> <br />
<button id="resume-animation1">動畫 1 繼續</button>
<button id="resume-animation2">動畫 2 繼續</button>
<button id="reset">Restart</button>

<script>
$("#trigger-animation1").on("click",function(){
  tl1.pause();
});

$("#trigger2").on("click",function(){
  tl2.pause();
});
$("#resume-animation1").on("click",function(){
  tl1.resume();  
});
$("#resume-animation2").on("click",function(){
  tl2.resume();  
});
$("#reset").on("click",function(){
  tl1.restart();
  tl2.restart();
});
</script>

透過上面的作法,我們可以監聽點擊按鈕的事件,來個別控制時間軸。

這個 CodePen 中,包含了上述各個案例實做出來的樣貌,作為參考。

透過 GSAP 製作預載動畫 (preload animation)

藉由 GSAP,我們可以為自己的網站加入預載動畫 (preload animation),可以參考這個 CodePen 或是直接體驗我們公司網站的效果。

<!-- 這邊是預載動畫的圖層 -->
<div id="preload">
  <div id="logo_preload">
    <div id="mask"></div>
  </div>
  <div id="bars">
    <div class="bar" id="bar1"></div>
    <div class="bar" id="bar2"></div>
    <div class="bar" id="bar3"></div>
    <div class="bar" id="bar4"></div>
    <div class="bar" id="bar5"></div>
  </div>
</div>
<!-- 以下是網站實際內容 --->
<div>
  <header id="masthead" class="site-header"><div class="site-branding">
<a href="https://www.applemint.tech/">
<img src="https://www.applemint.tech/wp-content/themes/applemint/assets/applemint-logo.png" srcset="" alt="Website Logo" scale="0">
</a></div></header>
</div>
#preload {
  position: fixed;
  background-color: #fff;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
}
#preload #logo_preload {
  position: absolute;
  width: 300px;
  height: 300px;
  top: 50%;
  transform: translate(-50%, -50%);
  left: 50%;
  background-image: url("https://www.applemint.tech/wp-content/themes/applemint/assets/favicon25.svg");
  background-repeat: no-repeat;
  background-position: center;
}
#preload #logo_preload #mask {
  position: absolute;
  background: #fff;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
#preload #bars {
  position: absolute;
  z-index: 20;
  width: 100%;
  height: 100%;
  opacity: 0;
}
#preload #bars .bar {
  height: 20vh;
  background: #00bbcc;
  position: absolute;
  width: 100%;
  right: 0;
}
#preload #bars #bar1 {
  top: 0%;
}
#preload #bars #bar2 {
  top: 20%;
}
#preload #bars #bar3 {
  top: 40%;
}
#preload #bars #bar4 {
  top: 60%;
}
#preload #bars #bar5 {
  top: 80%;
}

.site-header {
  background-color: #fff;
  display: flex;
  height: 87px;
  width: 100%;
  align-items: center;
  -ms-align-items: center;
  z-index: 998;
}
/** 這段是參考這個 CodePen https://codepen.io/ahsanrathore/pen/MwppEB,主要的功能在估算頁面需要載入的時間 */
var height = 100, // height of a progress bar in percentage
    perfData = window.performance.timing, // The PerformanceTiming interface
    EstimatedTime = -(perfData.loadEventEnd - perfData.navigationStart), // Calculated Estimated Time of Page Load which returns negative value.
    time = parseInt((EstimatedTime/1000)%60)*100; //Converting EstimatedTime from miliseconds to seconds.
    
/** 用 jQuery 來製作預載動畫顯示 logo 的效果 */
$("#mask").animate({
  height: 100-height+"%",
}, time);

/** 在前面的動畫載入完畢後,接續製作水平長條的動畫 */
var tl = new TimelineMax();
setTimeout(function(){
  // gasp.to("#bar1", );
  tl.to("#logo_preload", {duration: 0.3,opacity:0})
    .to("#bars", {duration:0.3,opacity:1}, "-=0.2")
    .to("#bar1", {duration:0.3,width:0}, "-=0.1")
    .to("#bar2", {duration:0.3,width:0}, "-=0.1")
    .to("#bar3", {duration:0.3,width:0}, "-=0.1")
    .to("#bar4", {duration:0.3,width:0}, "-=0.1")
    .to("#bar5", {duration:0.3,width:0}, "-=0.1")
    .to("#preload", {duration: 0.3, height:0});
}, time);

物件導向簡介

雖然物件導向本身就可以成為一次鐵人賽的主題,但我們這邊只針對 WordPress 與 JavaScript 所涉及的部分稍做簡介。

儘管物件導向聽起來很抽象,但我們平常在分類身邊周遭事物時,很自然的都會用上物件導向的觀念,譬如動物的分類,可以化簡為下面的語法:

function 動物( type, feet, specie) {
  this.類型 = type;
  this.腳數 = feet;
  this.品種 = specie;
}

var 烏龜 = new 動物( '爬蟲類', 4, '綠蠵龜' );
烏龜['類型']; //回傳「爬蟲類」

其中 new 的意思,代表著我要把原本「動物」抽象的概念,實體化成一個真正的物體「烏龜」。除了烏龜以外,我們也可以重複創造新的動物,譬如 var 帝雉 = new 動物( '鳥類', 2, '台灣帝雉' );
今天之所以帶到物件導向的話題,是為了說明在 GSAP 中,new TimelineMax(); 這個過程的意義。至於物件導向中的其他觀念,如「繼承」,則不在這次所要涵蓋的範圍中。

結語

今天的主題和 WordPress 的直接關係比較少,主要仍是在介紹如何透過 GSAP 這款函式庫,使用時間軸來安排網頁動畫。事實上,WordPress 有許多頁面編輯器 (page builder) 外掛,替網站加入不同的動態效果,如 ElementorDiviAvada 等。
除了介紹 GSAP 的實作方法外,我們也藉此了解物件導向的基本概念。我們在後續篇章的例子中,繼續了解如何藉由將物件實體化,更加活用不同的函式庫,甚至是 WordPress 的核心功能。
下一章,我們將會介紹許多業主、客戶很喜歡的函式庫:投影片輪播 (sliders)。

延伸閱讀

Tips for Writing Animation Code Efficiently
GSAP 官方說明文件
GSAP 速查表


上一篇
Day 15 用 WordPress 製作隨視窗捲動的動畫 (animation on scroll)
下一篇
Day 17 用 WordPress 製作投影片輪播 (slider) 效果
系列文
WordPress 客製化從 0 開始30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言